; Completar aqu'i las funciones sin el _C final (Ejemplo: "copiar" en vez de "copiar_C")
; Recuerde reemplazar las llamadas a las funciones en C por estas nuevas



; void copiar_C ( Uint8* img1, int screen_w, int screen_h, Uint8* img2);

global copiar
	
%define p_img1 ebp+8
%define bytes_ancho ebp+12
%define filas ebp+16
%define p_img2 ebp+20


section .text
copiar:	
	push ebp
	mov ebp, esp
	push edi
	push esi
	push ebx

	mov eax,[bytes_ancho]
	mul dword [filas] ; en eax tengo el total de pixeles
	
	mov esi, [p_img1]
	mov edi, [p_img2]
_ciclo:
	cmp eax, 16
	jl _procesoResto
	movups xmm0,[esi] 
	movups [edi],xmm0
	
	add esi,16
	add edi,16
	sub eax,16

	jmp _ciclo
	
_procesoResto:
	cmp eax,0
	je fin_C 
	
	mov edx, [esi]
	mov [edi], edx
	
	add esi,4
	add edi,4
	sub eax,4
	
	jmp _procesoResto


fin_C:	
	pop ebx
	pop esi
	pop edi
	
	leave
	ret

	
; void copiarInvertido_C ( Uint8* img1, int screen_w, int screen_h, Uint8* img2);
	
	
global copiarInvertido
	
%define p_img1 ebp+8
%define bytes_ancho ebp+12
%define filas ebp+16
%define p_img2 ebp+20


section .text
copiarInvertido:	
	push ebp
	mov ebp, esp
	push edi
	push esi
	push ebx

	mov eax,[bytes_ancho]
	mov ecx, [filas] ; 
	
	mov ebx,eax
	sub ebx,16
	
	mov esi, [p_img1]
	mov edi, [p_img2]
	
		
_cicloFilas:
	
	xor edx,edx
	add edx,ebx
	
	
_cicloCol:
	movups xmm0,[esi]
	
	pshufd xmm1,xmm0, 00011011b
		
	movups [edi+edx],xmm1
	
	
	sub edx,16
	add esi,16
		
	
	cmp edx,0
	
	jl _loop
	jmp _cicloCol


	
_loop:	
	add edi,eax
	loop _cicloFilas


fin_CI:	
	pop ebx
	pop esi
	pop edi
	
	leave
	ret
	
	
	
	
	
	
	
;void zoom_C(Uint8* foto, Uint32 w, Uint32 h, Uint8* zoom);
	
	
global zoom
	
%define p_img1 ebp+8
%define bytes_ancho ebp+12
%define filas ebp+16
%define p_areaZoom ebp+20


section .text
zoom:	
	push ebp
	mov ebp, esp
	push edi
	push esi
	push ebx

	mov eax,[bytes_ancho]
	mov ecx, [filas] ; 
	
	mov esi, [p_img1]
	mov edi, [p_areaZoom]
	
		
_cicloFilasZ:
	
	mov edx,eax ; pongo en edx el ancho de la fila.
	
	
_cicloColZ:
	
	movdqu xmm0,[esi]
	
	pshufd xmm1,xmm0, 01010000b
		
	movups [edi],xmm1
	movups [edi+2*eax],xmm1
	
	pshufd xmm1,xmm0, 11111010b
	add edi,16
	
	movups [edi],xmm1
	movups [edi+2*eax],xmm1
	
	
	
	sub edx,16
	add esi,16
	add edi,16
	
	
	cmp edx,0
	
	je _loopZ
	jmp _cicloColZ


	
_loopZ:	
	add edi,eax
	add edi,eax
	loop _cicloFilasZ


fin_Z:	
	pop ebx
	pop esi
	pop edi
	
	leave
	ret
	
	
	
	
;void blit(Uint8 *screen, int s_w, int s_h, Uint8 *image, int w, int h, int x, int y, Color rgb);


global blit_asm

%define p_screen ebp+8
%define s_ancho  ebp+12
%define s_alto ebp+16
%define p_img ebp+20
%define i_ancho ebp+24
%define i_alto ebp+28
%define pos_x ebp+32
%define pos_y ebp+36
%define color ebp+40

section .data align=16
mascara: dd 0x00FFFFFF,0x00FFFFFF,0x00FFFFFF,0x00FFFFFF
mascaraAlfa: dd 0xFF000000,0xFF000000,0xFF000000,0xFF000000

section .text
blit_asm:	
	push ebp
	mov ebp, esp
	push edi
	push esi
	push ebx
	
	mov edi, [p_screen]
	
	mov eax, [s_ancho]
	mul dword [pos_y]		
	sub eax, [s_ancho]		;en eax tenemos el puntero a la fila donde hay que sobreescribir
	add eax,[pos_x]		;sumamos tantos pixeles como la posición x
	shl eax,2			;pasamos de pixeles a bytes
	add edi,eax 		;nos posicionamos a principio del lugar donde hay que escribir

	mov esi,[p_img]
	
	movss xmm3,[color]
	pshufd xmm3,xmm3, 00000000b
	
	mov edx, mascara
	movdqu xmm5,[edx]

	pand xmm3, xmm5  		;limpiamos el alfa del color
		
	mov eax, [s_ancho]
	shl eax,2			; eax --> bytes el ancho del screen
	
	mov ebx, [i_ancho]
	shl ebx,2			; ebx --> bytes el ancho de la imagen

	mov ecx, [i_alto]
	
	mov edx, mascaraAlfa
	movdqu xmm6, [edx]
		
ciclo_FB:	
	xor edx,edx
ciclo_CB:	
	movdqu xmm0, [esi]	   ; xmm0 --> 4 pixeles de la imagen.
	pand xmm0, xmm5   	   ; limpiamos el alfa de la imagen
	movdqu xmm1, [edi+edx]	   ; xmm1 --> 4 pixeles del screen
	pand xmm1, xmm5   	   ; limpiamos el alfa del screen
	
	movdqu xmm2,xmm0	; xmm2 --> 4 pixeles de la imagen
	
	pcmpeqd xmm2,xmm3 	; xmm2 --> 0s en la figura y 1s lo que es rosa
	movdqu xmm4, xmm2      ; xmm4 --> la mascara del paso anterior
	pandn xmm2,xmm0		; xmm2 --> la figura y en 0 lo que era rosa
	pand xmm1,xmm4		; xmm1 --> fondo que no es figura y 0 en la figura
	por xmm2,xmm1		; xmm2 --> la figura con el fondo de la pantalla

	por xmm2, xmm6		; xmm2 --> la figura con el fondo de la pantalla con el alfa original
	movdqu [esi], xmm2
	
	add edx, 16
	add esi, 16
	
	cmp edx, ebx		
	jl ciclo_CB			; ciclamos en columnas si no se procesó toda la imagen

	add edi,eax
	loop ciclo_FB 

fin_B:	
	pop ebx
	pop esi
	pop edi
	
	leave
	ret
	

;global procesar4px	
;procesar4px:
%macro procesar4px 0
	pxor xmm5,xmm5
	
	pcmpeqd xmm7,xmm7
	psrld xmm7,24
	cvtdq2ps xmm7,xmm7		; xmm7 --> |255|255|255|255|
	rcpps xmm7,xmm7			; revierte
		
     	pxor xmm6,xmm6			; pone en 0 el xmm6 para desempaquetar
   	punpcklbw xmm0,xmm6		; desempaqueta word en xmm0
   	punpcklwd xmm0,xmm6		; desempaqueta double en xmm0 	
	cvtdq2ps xmm0,xmm0		; convierte de enteros a floats de 32 bits
	mulps xmm0,xmm7			; divide xmm0 por 255
		
	punpcklbw xmm1,xmm6		; desempaqueta en xmm1
   	punpcklwd xmm1,xmm6		; desempaqueta en xmm1  	
	cvtdq2ps xmm1,xmm1		; convierte de enteros a floats de 32 bits
	mulps xmm1,xmm7			; divide xmm1 por 255
	addps xmm0,xmm1			; suma el resultado a xmm0 que es el acumulador
			 
	punpcklbw xmm2,xmm6		; desempaqueta en xmm2
   	punpcklwd xmm2,xmm6		; desempaqueta en xmm2  	
	cvtdq2ps xmm2,xmm2		; convierte de enteros a floats de 32 bits
	mulps xmm2,xmm7			; divide xmm2 por 255
	addps xmm0,xmm2			; suma el resultado a xmm0 que es el acumulador
		
	punpcklbw xmm3,xmm6		; desempaqueta parte baja en xmm3
   	punpcklwd xmm3,xmm6		; desempaqueta parte baja en xmm3 	
	cvtdq2ps xmm3,xmm3		; convierte de enteros a floats de 32 bits
	mulps xmm3,xmm7			; divide xmm3 por 255
	addps xmm0,xmm3			; suma el resultado a xmm0 que es el acumulador

	pcmpeqd xmm3,xmm3
	psrld xmm3,31
	cvtdq2ps xmm3,xmm3		; xmm3 --> 1 | 1 | 1 | 1

	addps xmm0, xmm3		; suma 1 a xmm0
	rsqrtps xmm0,xmm0		; xmm0 --> 1 / raiz cuadrada de xmm0
	
	pcmpeqd xmm3,xmm3
	psrld xmm3,24
	cvtdq2ps xmm3,xmm3		; xmm3 --> 255 | 255 | 255 | 255 |
	mulps xmm0,xmm3			; multiplica resultado por 255
	
	movdqa [pixAnt],xmm0		; guardo el calculo del pixel anterior.
	
	cvtps2dq xmm0,xmm0		; convierte a enteros
	packssdw xmm0,xmm6	 	; empaqueta a word
	packuswb xmm0,xmm6		; empaqueta a byte
	por xmm5,xmm0
	
	; segundo pixel
	
	movdqa xmm0, [arriba]    ; xmm0 --> 4 pixeles correspondientes a arriba
	movdqa xmm2, [pixAnt] ; xmm2 --> 4 pixeles correspondientes a atras	
	movdqa xmm3, [derecha] ; xmm3 --> 4 pixeles correspondientes a adelante
	movdqa xmm1, [abajo]	  	  ; xmm1 --> 4 pixeles correspondientes a abajo
		

	pcmpeqd xmm7,xmm7
	psrld xmm7,24
	cvtdq2ps xmm7,xmm7		; xmm7 --> |255|255|255|255|
	rcpps xmm7,xmm7			; revierte xmm7
		
     	pxor xmm6,xmm6			; pone en 0 el xmm6 para desempaquetar
   	punpcklbw xmm0,xmm6		; desempaqueta parte baja a word en xmm0
   	punpckhwd xmm0,xmm6		; desempaqueta parte alta a double en xmm0  	
	cvtdq2ps xmm0,xmm0		; convierte de enteros a floats de 32 bits
	mulps xmm0,xmm7			; divide xmm0 por 255
		
	punpcklbw xmm1,xmm6		; desempaqueta parte baja a word en xmm1
   	punpckhwd xmm1,xmm6		; desempaqueta  parte alta a double en xmm1  	
	cvtdq2ps xmm1,xmm1		; convierte de enteros a floats de 32 bits
	mulps xmm1,xmm7			; divide xmm1 por 255
	addps xmm0,xmm1			; suma el resultado a xmm0 que es el acumulador
		
	mulps xmm2,xmm7			; divide xmm2 por 255
	addps xmm0,xmm2			; suma el resultado a xmm0 que es el acumulador
		
	punpcklbw xmm3,xmm6		; desempaqueta parte baja a word en xmm3
   	punpckhwd xmm3,xmm6		; desempaqueta parte alta a double en xmm3
	cvtdq2ps xmm3,xmm3		; convierte de enteros a floats de 32 bits
	mulps xmm3,xmm7			; divide xmm3 por 255
	addps xmm0,xmm3			; suma el resultado a xmm0 que es el acumulador
	
	pcmpeqd xmm3,xmm3
	psrld xmm3,31
	cvtdq2ps xmm3,xmm3		; xmm3 --> 1 | 1 | 1 | 1

	addps xmm0, xmm3		; suma 1 a xmm0
	rsqrtps xmm0,xmm0		; xmm0 --> 1 / raiz cuadrada de xmm0

	pcmpeqd xmm3,xmm3
	psrld xmm3,24
	cvtdq2ps xmm3,xmm3		; xmm3 --> 255 | 255 | 255 | 255 |
	mulps xmm0, xmm3		; multiplica resultado por 255
	
	movdqa [pixAnt],xmm0		; guardo el calculo del pixel anterior.
	
	cvtps2dq xmm0,xmm0		; convierte a enteros
	packssdw xmm0,xmm6	 	; empaqueta a word
	packuswb xmm0,xmm6		; empaqueta a byte
	
	psllq xmm0,32			; xmm0 --> 0 | 0 | 2º px calculado | 0
	por xmm5,xmm0
	
	
	; tercer pixel	
	
	movdqa xmm0, [arriba]	; xmm0 --> 4 pixeles correspondientes a arriba
	movdqa xmm2, [pixAnt]	; xmm2 --> 4 pixeles correspondientes a atras
	movdqa xmm3, [derecha] 		; xmm3 --> 4 pixeles correspondientes a adelante
	movdqa xmm1, [abajo] ; xmm1 --> 4 pixeles correspondientes a abajo
	
	pcmpeqd xmm7,xmm7
	psrld xmm7,24
	cvtdq2ps xmm7,xmm7		; xmm7 --> |255|255|255|255|
	rcpps xmm7,xmm7			; revierte
		
     	pxor xmm6,xmm6			; pone en 0 el xmm6 para desempaquetar
   	punpckhbw xmm0,xmm6		; desempaqueta parte alta a word en xmm0
   	punpcklwd xmm0,xmm6		; desempaqueta parte baja a double en xmm0
	cvtdq2ps xmm0,xmm0		; convierte de enteros a floats de 32 bits
	mulps xmm0,xmm7			; divide xmm0 por 255
		
	punpckhbw xmm1,xmm6		; desempaqueta parte alta a word en xmm1
   	punpcklwd xmm1,xmm6		; desempaqueta parte baja a double en xmm1
	cvtdq2ps xmm1,xmm1		; convierte de enteros a floats de 32 bits
	mulps xmm1,xmm7			; divide xmm1 por 255
	addps xmm0,xmm1			; suma el resultado a xmm0 que es el acumulador
		
	mulps xmm2,xmm7			; divide xmm2 por 255
	addps xmm0,xmm2			; suma el resultado a xmm0 que es el acumulador
		
	punpckhbw xmm3,xmm6		; desempaqueta parte alta a word en xmm3
   	punpcklwd xmm3,xmm6		; desempaqueta parte alta a word en xmm3
	cvtdq2ps xmm3,xmm3		; convierte de enteros a floats de 32 bits
	mulps xmm3,xmm7			; divide xmm3 por 255
	addps xmm0,xmm3			; suma el resultado a xmm0 que es el acumulador
	
	pcmpeqd xmm3,xmm3
	psrld xmm3,31
	cvtdq2ps xmm3,xmm3		; xmm3 --> 1 | 1 | 1 | 1
	addps xmm0, xmm3		; suma 1 a xmm0
	rsqrtps xmm0,xmm0		; xmm0 --> 1 / raiz cuadrada de xmm0

	pcmpeqd xmm3,xmm3
	psrld xmm3,24
	cvtdq2ps xmm3,xmm3		; xmm3 --> 255 | 255 | 255 | 255 |
	mulps xmm0, xmm3		; multiplica resultado por 255
	
	movdqa [pixAnt],xmm0		; guardo el calculo del pixel anterior.
	
	cvtps2dq xmm0,xmm0		; convierte a enteros
	packssdw xmm0,xmm6	 	; empaqueta a word
	packuswb xmm0,xmm6		; empaqueta a byte
	
	pslldq xmm0, 8			; xmm0 --> 0 | 3º px calculado | 0 | 0 |
	por xmm5,xmm0
	
	; cuarto pixel
	
	movdqa xmm0, [arriba] ; xmm0 --> 4 pixeles correspondientes a arriba
	movdqa xmm2, [pixAnt] ; xmm2 --> 4 pixeles correspondientes a atras	  	  
	movdqa xmm3, [derecha]  ; xmm3 --> 4 pixeles correspondientes a adelante
	movdqa xmm1, [abajo] ; xmm1 --> 4 pixeles correspondientes a abajo

	pcmpeqd xmm7,xmm7
	psrld xmm7,24
	cvtdq2ps xmm7,xmm7		; xmm7 --> |255|255|255|255|
	rcpps xmm7,xmm7			; revierte
		
     	pxor xmm6,xmm6			; ponge en 0 el xmm6 para desempaquetar
   	punpckhbw xmm0,xmm6		; desempaqueta parte alta a word en xmm0
   	punpckhwd xmm0,xmm6		; desempaqueta parte alta a double en xmm0  	
	cvtdq2ps xmm0,xmm0		; convierte de enteros a floats de 32 bits
	mulps xmm0,xmm7			; divide xmm0 por 255
		
	punpckhbw xmm1,xmm6		; desempaqueta parte alta a word en xmm1
   	punpckhwd xmm1,xmm6		; desempaqueta parte alta a double en xmm1
	cvtdq2ps xmm1,xmm1		; convierte de enteros a floats de 32 bits
	mulps xmm1,xmm7			; divide xmm1 por 255
	addps xmm0,xmm1			; suma el resultado a xmm0 que es el acumulador
		
	mulps xmm2,xmm7			; divide xmm2 por 255
	addps xmm0,xmm2			; suma el resultado a xmm0 que es el acumulador
	
	punpckhbw xmm3,xmm6		; desempaqueta parte alta a word en xmm3
   	punpckhwd xmm3,xmm6		; desempaqueta parte alta a double en xmm3
	cvtdq2ps xmm3,xmm3		; convierte de enteros a floats de 32 bits
	mulps xmm3,xmm7			; divide xmm3 por 255
	addps xmm0,xmm3			; suma el resultado a xmm0 que es el acumulador

	pcmpeqd xmm3,xmm3
	psrld xmm3,31
	cvtdq2ps xmm3,xmm3		; xmm3 --> 1 | 1 | 1 | 1
	
	addps xmm0, xmm3		; suma 1 a xmm0
	rsqrtps xmm0,xmm0		; xmm0 --> 1 / raiz cuadrada de xmm0

	pcmpeqd xmm3,xmm3
	psrld xmm3,24
	cvtdq2ps xmm3,xmm3		; xmm3 --> 255 | 255 | 255 | 255 |
	mulps xmm0, xmm3		; multiplica resultado por 255
	
	cvtps2dq xmm0,xmm0		; convierte a enteros
	packssdw xmm0,xmm6	 	; empaqueta a word
	packuswb xmm0,xmm6		; empaqueta a byte
	
	pslldq xmm0, 12			; xmm0 --> 4º px calculado | 0 | 0 | 0 |
	por xmm5,xmm0
%endmacro


	
;bool negative(Uint8* screen, Uint32 w, Uint32 h)
global negative_asm

%define p_screen ebp+8
%define ancho  ebp+12
%define alto ebp+16

section .data align=16
arriba: dd 0,0,0,0
abajo: dd 0,0,0,0
izquierda: dd 0,0,0,0
derecha: dd 0,0,0,0
pixAnt: dd 0,0,0,0


section .text
negative_asm:	
	push ebp
	mov ebp, esp
	push edi
	push esi
	push ebx
	
	mov edi, [p_screen]
	mov ebx, [ancho]
	shl ebx, 2			; ebx --> ancho de la imagen en bytes
	
	mov ecx, [alto] 		; ecx --> alto de la imagen
	
	mov eax,ecx
	
	mul ebx
	mov esi, eax		; esi --> la cantidad de pixeles hasta la fila anterior a la última

	mov eax, ebx
	; procesamos los primeros 4 pixeles de la imagen
	
	pxor xmm0, xmm0
	movdqa [arriba], xmm0
	movdqu xmm2,[edi]    ; puse los 4 primeros pixles y xmm2 va a tener el pixel de la izq
	pslldq xmm2, 4		; pongo en cero los 4 bytes menos significativos.
	movdqa [izquierda] , xmm2
	movdqu xmm3, [edi+4]	; en xmm3 pongo los 4 prixeles derechos
	movdqa [derecha] , xmm3
	movdqu xmm1, [edi+ebx]	; tomo los pixeles de abajo
	movdqa [abajo] , xmm1
	
	;call procesar4px
	procesar4px
	
	movdqu [edi], xmm5 		  ; movemos el resultado al pixel a calcular
	add edi,ebx
	sub edi,16
	pxor xmm0,xmm0
	movdqa [arriba], xmm0
	
	movdqu xmm2, [edi-4]
	movdqa [izquierda], xmm2
	
	movdqu xmm3, [edi]
	psrldq xmm3, 4
	movdqa [derecha],xmm3
	
	movdqu xmm1, [edi+ebx]
	movdqa [abajo],xmm1
	
	;call procesar4px
	procesar4px
	
	movdqu [edi], xmm5
	
	mov eax,ecx
	sub eax,2
	mul ebx
	add edi,eax
	movdqu xmm0,[edi]
	movdqa [arriba],xmm0
	
	add edi,ebx
	movdqu xmm2, [edi-4]
	movdqa [izquierda],xmm2
	
	movdqu xmm3,[edi]
	psrldq xmm3,4
	movdqa [derecha], xmm3
	
	pxor xmm1,xmm1
	movdqa [abajo], xmm1
	
	;call procesar4px
	procesar4px
	
	movdqu [edi], xmm5
	
	sub edi,ebx
	add edi,16
	sub edi,ebx
	movdqu xmm0, [edi]
	movdqa [arriba], xmm0
	
	add edi,ebx
	movdqu xmm2, [edi]
	pslldq xmm2, 4
	movdqa [izquierda], xmm2
	
	movdqu xmm3, [edi+4]
	movdqa [derecha], xmm3
	
	pxor xmm1,xmm1
	movdqa [abajo], xmm1
	
	;call procesar4px
	procesar4px
	
	movdqu [edi], xmm5	
	
	; procesamos el borde superior sin incluir los primeros 4 pixeles y los ultimos 4 pixeles
procesar_borde_izq:	
	mov edi,[p_screen]
	mov ebx,[ancho]
	shl ebx, 2			; ebx --> ancho de la imagen en bytes
	sub ebx, 32
	xor ecx,ecx
	
	add edi,16		; edi apunta al primer pixel a procesar
ciclo_borde_sup:
	cmp ecx,ebx
	jl quedan_pixeles_borde_sup
	jmp procesar_izq
	
quedan_pixeles_borde_sup:
	pxor xmm0,xmm0
	movdqu [arriba],xmm0
	movdqu xmm2, [edi-4]
	movdqa [izquierda], xmm2
	movdqu xmm3, [edi+4]
	movdqa [derecha], xmm3
	movdqu xmm1, [edi+ebx+32]
	movdqa [abajo], xmm1
	
	;call procesar4px
	procesar4px
	
	movdqu [edi], xmm5
	add edi,16
	add ecx,16
	jmp ciclo_borde_sup

procesar_izq:
	
	mov edi,[p_screen]
	mov ebx,[ancho]
	shl ebx, 2			; ebx --> ancho de la imagen en bytes
	mov edx,[alto]
	xor ecx,ecx
					; edi --> apunta al comienzo
	dec edx				
	dec edx				; hay que restar las dos, por la primera y por la ultima.
	
ciclo_borde_izq:	
	cmp ecx, edx
	jl quedan_pixeles_borde_izq
	jmp procesar_abajo
quedan_pixeles_borde_izq:
	movdqu xmm0, [edi]
	movdqa [arriba], xmm0
	movdqu xmm2, [edi+ebx]
	pslldq xmm2, 4
	movdqa [izquierda], xmm2
	movdqu xmm3, [edi+ebx+4]
	movdqa [derecha], xmm3
	movdqu xmm1, [edi+2*ebx]
	movdqa [abajo], xmm1
	
	;call procesar4px
	procesar4px
	
	add edi,ebx
	movdqu [edi], xmm5
	
	inc ecx
	jmp ciclo_borde_izq
	
procesar_abajo:
	mov edi,[p_screen]
	mov ebx,[ancho]
	shl ebx, 2			; ebx --> ancho de la imagen en bytes
	mov eax,[alto]

	sub eax,2
	mul ebx
	add edi, eax
	add edi,16			; edi apunta al 5to pixel de la fila de abajo.

	mov ecx,16
	
ciclo_abajo:	
	cmp ecx,ebx
	jl quedan_pixeles_abajo
	jmp procesar_interior
quedan_pixeles_abajo:
	movdqu xmm0, [edi]
	movdqa [arriba], xmm0
	movdqu xmm2, [edi+ebx-4]
	movdqa [izquierda], xmm2
	movdqu xmm3, [edi+ebx+4]
	movdqa [derecha], xmm3
	pxor xmm1,xmm1
	movdqa [abajo], xmm1
	
	;call procesar4px
	procesar4px
	
	movdqu [edi+ebx], xmm5
	add edi,16
	add ecx,16
	jmp ciclo_abajo
	
	
procesar_interior:
	mov edi,[p_screen]
	mov ebx,[ancho]
	shl ebx, 2			; ebx --> ancho de la imagen en bytes
	mov eax,[alto]

	sub eax,2			; eax tiene alto -2 
	
	add edi,16			; edi empieza en el 5to pixel de la primera fila
	xor edx,edx
ciclo_filas_interior:
	cmp edx,eax
	jl quedan_filas_interior
	jmp procesar_der
	
quedan_filas_interior:
	xor ecx,ecx
	add ecx,32			; 16 por el pixel de la columna 0 + 16 por el pixel de la ultima columna
	
ciclo_columnas_interior:	
	cmp ecx,ebx
	jl quedan_px_col_interior

bajar_fila:
	add edi,32
	inc edx				; marcamos una fila mas procesada
	jmp ciclo_filas_interior
	
quedan_px_col_interior:
	movdqu xmm0, [edi]
	movdqa [arriba], xmm0
	movdqu xmm2, [edi+ebx-4]
	movdqa [izquierda],xmm2
	movdqu xmm3, [edi+ebx+4]	
	movdqa [derecha], xmm3
	movdqu xmm1, [edi+2*ebx]
	movdqa [abajo], xmm1

	;call procesar4px
	procesar4px
	
	movdqu [edi+ebx], xmm5
	add edi,16
	add ecx,16
	jmp ciclo_columnas_interior

	
procesar_der:

	mov edi,[p_screen]
	add edi,ebx
	sub edi,16		; edi apunta al final de la primera fila (4 pixeles antes)		
	xor ecx,ecx

ciclo_borde_der:	
	cmp ecx, edx
	jl quedan_pixeles_borde_der
	jmp fin_N
	
quedan_pixeles_borde_der:
	movdqu xmm0, [edi]
	movdqa [arriba], xmm0
	movdqu xmm2, [edi+ebx-4]
	movdqa [izquierda], xmm2
	movdqu xmm3, [edi+ebx]
	psrldq xmm3,4
	
	movdqa [derecha], xmm3
	movdqu xmm1, [edi+2*ebx]
	movdqa [abajo], xmm1

	;call procesar4px
	procesar4px
	
	add edi, ebx
	movdqu [edi], xmm5	

	inc ecx
	jmp ciclo_borde_der
	
fin_N:	
	pop ebx
	pop esi
	pop edi
	
	leave
	ret
	
	

	
;void generarPlasma(Uint8* pixeles, int h, int w, Uint16 &vel_vertical_0, 
;	Uint16 &vel_vertical_1, Uint16 &vel_horizontal_0, Uint16 &vel_horizontal_1)

global generarPlasma_asm

%define p_screen ebp+8
%define alto ebp+12
%define ancho  ebp+16
%define vel_ver_0  ebp+20
%define vel_ver_1  ebp+24
%define vel_hor_0  ebp+28
%define vel_hor_1  ebp+32
%define colores  ebp+36

%define vertical_0  ebp-4
%define horizontal_0  ebp-8
%define vertical_1  ebp-12
%define horizontal_1  ebp-16

section .data 	align=16
horizontal_0_col_actual: dd 0,0,0,0		; para optimizar
horizontal_1_col_actual: dd 0,0,0,0		; para optimizar

section .text
generarPlasma_asm:
	push ebp
	mov ebp, esp
	sub esp, 16
	push edi
	push esi
	push ebx
	
	mov edi, [p_screen]	; en edx voy a tener el puntero al screen.
	mov ecx, [alto]		; en ecx voy a tener el contador de las filas.
	mov ebx, [ancho]	; en ebx ancho del screen
	
	shl ebx,2	; eax --> ancho en bytes 
	
	mov esi, [colores]
	mov dword [horizontal_1], 0
	mov edx, [vel_hor_0]
	mov edx, [edx]
	mov [horizontal_0],edx
		
_ciclo_F_GP:
	xor edx, edx
	mov eax, [vel_ver_0]
	mov eax,[eax]	
	mov [vertical_0], eax
	mov dword [vertical_1], 1
	
	mov eax, 511
	and [horizontal_0], eax
	mov eax, [horizontal_0]
	lea eax, [esi + 4*eax]
	movdqu xmm3, [eax]
	pshufd xmm3, xmm3, 00000000
	movdqa [horizontal_0_col_actual], xmm3
	
	mov eax, 511	
	and [horizontal_1], eax
	mov eax, [horizontal_1]
	lea eax, [esi + 4*eax]
	movdqu xmm5, [eax]
	pshufd xmm5, xmm5, 00000000
	movdqa [horizontal_1_col_actual],xmm5
	
_ciclo_C_GP:
	mov eax, 511
	and [vertical_0], eax
	and [vertical_1], eax

	mov eax, [vertical_0]
	movdqu xmm0,[esi + 4*eax] ;aca tengo el dato vertical_0

	mov eax, [vertical_1]
	movdqu xmm2,[esi + 4*eax] ;aca tengo el dato vertical_1

	movdqa xmm3,[horizontal_0_col_actual]	; optimizacion leemos alineado
	
	movdqa xmm5, [horizontal_1_col_actual]	; optimizacion leemos alineado
	
	movdqu xmm1, xmm0
	paddd xmm1, xmm2
	paddd xmm1, xmm3
	paddd xmm1, xmm5   ; xmm1 = x
	
; comienzo proceso de 4 pixeles de plasma
proc_4_pixel:
	psrad xmm1,4		; xmm1 = x3>>4, x2>>4, x1>>4, x0>>4
	pcmpeqd xmm2,xmm2	; xmm2 = 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
	movdqu xmm4, xmm2	; xmm4 = 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
	psrld xmm2,31		; xmm2 = 1, 1, 1, 1
	movdqu xmm3,xmm2	; xmm3 = 1, 1, 1, 1
	pslld xmm2,7		; xmm2 = 128, 128, 128, 128
	paddd xmm1,xmm2		; xmm1 = 128+x3>>4, 128+x2>>4, 128+x1>>4, 128+x0>>4
				; xmm1 = index3, index2, index1, index0
	psrld xmm4,24		; xmm4 = 255,255,255,255
	pand xmm1,xmm4		; xmm1 = index3, index2, index1, index0  (Truncado a Uint8)
	
	movdqu xmm2,xmm1	; xmm2 = index3, index2, index1, index0
	pslld xmm2,2		; xmm2 = index3<<2, index2<<2, index1<<2, index0<<2
	
	; hasta aqui tenemos :
	; xmm1 = index, ...,
	; xmm2 = index<<2, ...
	; xmm3 = 1, ...

	pslld xmm3, 6		; xmm3 = 64,64,64,64
	movdqu xmm4, xmm1	; xmm4 = index3, index2, index1, index0
	pcmpeqd xmm4, xmm3	; xmm4 = index==64? ...
	movdqu xmm5, xmm1	; xmm5 = index3, index2, index1, index0
	pcmpgtd xmm5, xmm3	; xmm5 = index>64? ...
	por xmm4, xmm5		; xmm4 = index>=64 ...
	
	; hasta aqui tenemos :
	; xmm1 = index, ...,
	; xmm2 = index<<2, ...
	; xmm3 = 64, ...
	; xmm4 = index>=64 ...
	
	movdqu xmm5, xmm2	; xmm5 = index3<<2, index2<<2, index1<<2, index0<<2
	movdqu xmm6,xmm3	; xmm6 = 64, ... 64
	psrld xmm6,6		; xmm6 = 1, ... 1
	paddd xmm2, xmm6	; xmm2 = index3<<2+1, index2<<2+1, index1<<2+1, index0<<2+1
	
	
	pcmpeqd xmm6,xmm6
	psrld xmm6, 24		; xmm6 = 255,255,255,225
	
	pand xmm2, xmm6		; xmm2 truncado a Uint8
	pand xmm5, xmm6		; xmm5 truncado a Uint8

	movdqu xmm7, xmm2	; 
	pslld xmm7, 16
	por xmm2, xmm7		; xmm2 = index3<<2+1 x2 , index2<<2+1 x2, index1<<2+1 x2, index0<<2+1 x2 (x2 = rep2, cada valor en dw)
	
	movdqu xmm7, xmm2
	psllw xmm7, 8
	por xmm2, xmm7		; xmm2 = index3<<2+1 x4 , index2<<2+1 x4, index1<<2+1 x4, index0<<2+1 x4 (x4 = rep4, cada valor en db)
	

	movdqu xmm7, xmm5	; 
	pslld xmm7, 16
	por xmm5, xmm7		; xmm5 = index3<<2 x2 , index2<<2 x2, index1<<2 x2, index0<<2 x2 (x2 = rep2, cada valor en dw)
	
	movdqu xmm7, xmm5
	psllw xmm7, 8
	por xmm5, xmm7		; xmm5 = index3<<2 x4 , index2<<2 x4, index1<<2 x4, index0<<2 x4 (x4 = rep4, cada valor en db)

	psrld xmm5,8
	pslld xmm5,8		; xmm5 = 0, index3<<2 x3, 0, index2<<2 x3 ...
	
	pcmpeqd xmm7,xmm7
	psrld xmm7,16
	packsswb xmm7,xmm7	; xmm7 = 0,255,0,255, ...
	movdqu xmm6, xmm7
	
	psubb xmm7, xmm2 
	pand xmm7, xmm6
	paddb xmm5,xmm7
	
	movdqu xmm0, xmm4	; muevo la mascara de >= 64
	pandn xmm0, xmm5	; aplico la mascara negada (para que quede < 64) y guardo el primer resultado en xmm0
	
	; Aquí empieza el segundo if
	pcmpeqd xmm5,xmm5
	pslld xmm5,16
	packsswb xmm5,xmm5	; xmm5 = 255, 0 ,255,0,255, ...
	movdqu xmm6, xmm2	; xmm6 = index3<<2+1 x4 , index2<<2+1 x4, index1<<2+1 x4, index0<<2+1 x4 (x4 = rep4, cada valor en db)
	psrld xmm6,24		; xmm6 = 0 x3, index3<<2+1, 0x3, index2<<2+1, ....
	paddb xmm5,xmm6		;
	
	movdqu xmm6, xmm1	; muevo los index a xmm6
	pslld xmm3, 1		; xmm3 = 128,128,128,128
	
	pcmpeqd xmm6, xmm3	; xmm6 = index == 128 ? ...
	movdqu xmm7, xmm1	; muevo los index a xmm7
	pcmpgtd xmm7, xmm3	; xmm7 = index > 128 ?
	por xmm6, xmm7		; xmm6 = index >= 128 ?
	movdqu xmm3, xmm6
	
	pcmpeqd xmm7, xmm7
	pandn xmm6, xmm7	; xmm6 = index < 128 ?
	
	pand xmm4, xmm6		; xmm4 = index >= 64 and index < 128
	pand xmm5, xmm4		; xmm5 = resultado con mascara
	
	movdqu xmm4, xmm3	; en xmm4 dejo el index >= 128? (Para el prox. if)
	por xmm0, xmm5		; xmm0 = ya tiene los dos primeros if procesados.
	
	; Aquí empieza el tercer if
	pcmpeqd xmm5, xmm5	; xmm5 = 255 x16
	psubb xmm5, xmm2	; xmm5 = 255 - ((index<<2)+1) rep 16
	
	pcmpeqd xmm3, xmm3	; xmm3 = 255 x16
	psrld xmm3, 31		; xmm3 = 1,1,1,1
	pslld xmm3, 7		; xmm3 = 128,128, ...
	movdqu xmm6, xmm3
	psrld xmm6,1		; xmm6 = 64, 64, ...
	paddd xmm3, xmm6	; xmm3 = 192, 192, ...
	movdqu xmm6, xmm1	; xmm6 = index ...
	pcmpeqd xmm6, xmm3	; xmm6 = index == 192 ? ...
	movdqu xmm7, xmm1	; xmm7 = index ...
	pcmpgtd xmm7, xmm3	; xmm6 = index > 192 ? ...
	por xmm6, xmm7		; xmm6 = index >= 192 ? ...
	
	movdqu xmm7, xmm6
	pandn xmm6, xmm4	; xmm6 = index >= 128 and index < 192? ...
	pand xmm5, xmm6		; xmm5 = mascara aplicada
	por xmm0, xmm5		; xmm0 = ya tiene los tres primeros if procesados.
	movdqu xmm4, xmm7	; en xmm4 dejo el index >= 192 (Para el prox. if)
	
	; Aquí empieza el cuarto if
	psrld xmm2, 24		; 0 rep 3, (index << 2 + 1), 0 rep3, (index << 2 + 1) ....
	
	pcmpeqd xmm3, xmm3	; xmm3 = 255 x16
	psrld xmm3, 31		; xmm3 = 1,1,1,1
	pslld xmm3, 8		; xmm3 = 256,256, ...
	
	movdqu xmm5, xmm1	; xmm5 = index ...
	pcmpeqd xmm5,xmm3	; xmm5 = index == 256? ...
	movdqu xmm6, xmm1	; xmm6 = index ...
	pcmpgtd xmm6, xmm3	; xmm6 = index > 256? ...
	por xmm5, xmm6		; xmm6 = index >= 256
	pandn xmm5, xmm4	; xmm5 = index >= 192 and index < 256
	pand xmm2, xmm5		; xmm2 = resultado con mascara aplicada
	por xmm0, xmm2		; xmm0 = ya tiene los cuatro primeros if procesados.
	
	; Nota el 5to if no se ejecuta nunca => no se procesa.
	pcmpeqd xmm2, xmm2	; xmm2 = 255 x16
	psrld xmm2,16
	pand xmm0, xmm2		; truncamos los valores mas significativos con 0
	pslld xmm2, 31
	psrld xmm2, 7		; dejo el número 0x01000000 rep 4 veces.
	paddd xmm0, xmm2


; fin proceso de 4 pixeles de plasma

	movdqu [edi],xmm0
	
	add dword [vertical_0],4
	add dword [vertical_1],4
	
	
	add edi,16
	add edx, 16
	cmp edx, ebx
	jnl loop_F
	jmp _ciclo_C_GP
	
loop_F:	

	inc dword [horizontal_1]	
	inc dword [horizontal_0]
	
	dec ecx
	cmp ecx, 0
	je fin_GP
	jmp _ciclo_F_GP
	

fin_GP:	

	mov eax, [vel_ver_0]
	add dword [eax], 4
	mov eax, [vel_hor_0]
	add dword [eax], 5

	pop ebx
	pop esi
	pop edi
	
	leave
	ret

